package com.milhouz.pokertimer;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.RingtoneManager;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.PowerManager;
import android.os.Vibrator;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.milhouz.pokertimer.constant.LogConstant;
import com.milhouz.pokertimer.constant.SavedStateConstant;
import com.milhouz.pokertimer.model.MainDataTimer;
import com.milhouz.pokertimer.util.TimerFormatter;

/**
 * Poker timer main activity.
 */
public class PokerTimer extends Activity {

	/** Menu "application settings" index */
	private static final int MENU_SETTINGS = Menu.FIRST;
	/** Menu "game preferences" index */
	private static final int MENU_PREFERENCES = Menu.FIRST + 1;

	/** Show settings request code */
	private static final int SHOW_SETTINGS = 2;
	/** Show preferences request code */
	private static final int SHOW_PREFERENCES = 1;

	// Components
	public TextView mCountdownTextView;
	public CountDown mCountdown;
	private long msElapsed;
	private boolean isRunning = false;

	public ImageButton mStartPauseButton;
	public ImageButton mNextRoundButton;
	public ImageButton mPreviousButton;
	public TextView mCurrentRoundText;
	public TextView mSmallBlindText;
	public TextView mBigBlindText;
	public TextView mCurrentRoundInfoText;
	public TextView mNextRoundInfoText;
	public ImageButton mResetButton;
	public ImageButton mBlindListButton;
	public ImageButton mPriceListButton;

	// Service managers
	public AudioManager mAudioManager;
	public PowerManager.WakeLock mWakeLock;

	/** Model of the timer */
	public MainDataTimer dataTimer;
	public boolean mFirstCallTimer = true;
	public boolean mIsActiveSound = true;
	public boolean mIsActiveVibrate = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		int orient = this.getWindowManager().getDefaultDisplay().getOrientation();
		Log.e(LogConstant.LOG_TAG, "ORIENTATION : " + orient);
		switch (orient) {
		case 0: // Portait
			setContentView(R.layout.main_portrait);
			break;
		case 1: // Landscape
			setContentView(R.layout.main_landscape);
			break;
		default:
			break;
		}
		dataTimer = (MainDataTimer) getLastNonConfigurationInstance();
		if (dataTimer == null) {
			// First launch
			dataTimer = new MainDataTimer(getString(R.string.default_players)//
					, getString(R.string.default_stack)//
					, getString(R.string.default_timeround)//
					, getString(R.string.default_firstsmallblind)//
					, getString(R.string.default_blindstep)//
					, getString(R.string.default_nbprices));
		}
		Log.d(LogConstant.LOG_TAG, dataTimer.toString());

		mCountdownTextView = (TextView) findViewById(R.id.timer);
		mStartPauseButton = (ImageButton) findViewById(R.id.buttonStart);
		mNextRoundButton = (ImageButton) findViewById(R.id.buttonNextRound);
		mPreviousButton = (ImageButton) findViewById(R.id.buttonPreviousRound);
		mCurrentRoundText = (TextView) findViewById(R.id.textRoundNumber);
		mSmallBlindText = (TextView) findViewById(R.id.textSmallBlindValue);
		mBigBlindText = (TextView) findViewById(R.id.textBigBlindValue);
		mCurrentRoundInfoText = (TextView) findViewById(R.id.currentRoundInfoText);
		mNextRoundInfoText = (TextView) findViewById(R.id.nextRoundInfoText);
		mResetButton = (ImageButton) findViewById(R.id.buttonReset);
		mBlindListButton = (ImageButton) findViewById(R.id.buttonBlindList);
		mPriceListButton = (ImageButton) findViewById(R.id.buttonPriceList);

		updateTextViews();

		// start/pause button listener
		mStartPauseButton.setOnClickListener(mStartListener);
		// reset button listener
		mResetButton.setOnClickListener(mResetListener);
		// next round button listener
		mNextRoundButton.setOnClickListener(mNextRoundListener);
		// previous round button listener
		mPreviousButton.setOnClickListener(mPreviousListener);
		// blind list button listener
		mBlindListButton.setOnClickListener(mBlindListListener);
		// price list button listener
		mPriceListButton.setOnClickListener(mPriceListListener);

		// Service Audio
		mAudioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);

		// TODO TEST Service Screen lock
		PowerManager powerManager = (PowerManager) getSystemService(Activity.POWER_SERVICE);
		mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, LogConstant.LOG_TAG);

		mCountdown = new CountDown(dataTimer.getCurrentRoundTime() * 60000, 1000);
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		// Used when the screen orientation is changed, in that case save the data of the Timer
		Log.i(LogConstant.LOG_TAG, "onRetainNonConfigurationInstance().");
		if (dataTimer == null) {
			dataTimer = new MainDataTimer(getString(R.string.default_players)//
					, getString(R.string.default_stack)//
					, getString(R.string.default_timeround)//
					, getString(R.string.default_firstsmallblind)//
					, getString(R.string.default_blindstep)//
					, getString(R.string.default_nbprices));
		}
		return dataTimer;
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, MENU_PREFERENCES, Menu.NONE, R.string.menu_preferences).setIcon(android.R.drawable.ic_menu_manage);
		menu.add(0, MENU_SETTINGS, Menu.NONE, R.string.menu_settings).setIcon(android.R.drawable.ic_menu_preferences);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);

		switch (item.getItemId()) {
		case (MENU_SETTINGS): {
			stopTimer();
			Intent i = new Intent(getApplicationContext(), PokerTimerSettings.class);
			startActivityForResult(i, SHOW_SETTINGS);
			return true;
		}
		case (MENU_PREFERENCES): {
			stopTimer();
			if (mFirstCallTimer) {
				Intent i = new Intent(getApplicationContext(), PokerTimerPreferences.class);
				startActivityForResult(i, SHOW_PREFERENCES);
			} else {
				AlertDialog.Builder alert = new AlertDialog.Builder(this);
				alert.setTitle(R.string.dialog_losepref_title);
				alert.setMessage(R.string.dialog_losepref_message);
				alert.setIcon(android.R.drawable.ic_dialog_alert);
				alert.setPositiveButton(R.string.dialog_losepref_positive, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						Intent i = new Intent(getApplicationContext(), PokerTimerPreferences.class);
						startActivityForResult(i, SHOW_PREFERENCES);
					}
				});
				alert.setNegativeButton(R.string.dialog_losepref_negative, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						startTimer();
					}
				});
				alert.show();
			}
			return true;
		}
		}
		return false;
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		Log.i(LogConstant.LOG_TAG, "onActivityResult request[" + requestCode + "], result[" + resultCode + "]");
		switch (requestCode) {
		case (SHOW_PREFERENCES): {
			updateFromPreferences();
		}
		case (SHOW_SETTINGS): {
			// impact settings update.
			SharedPreferences prefs = getSharedPreferences(PokerTimerSettings.APP_SETTINGS, Activity.MODE_PRIVATE);
			mIsActiveSound = prefs.getBoolean("activateSounds", mIsActiveSound);
			mIsActiveVibrate = prefs.getBoolean("activateVibrate", mIsActiveVibrate);
		}
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		Log.i(LogConstant.LOG_TAG, "onSaveInstanceState()");
		outState.putLong(SavedStateConstant.STATE_CHRONO_MS_ELAPSED, msElapsed);
		outState.putBoolean(SavedStateConstant.STATE_CHRONO_IS_RUNNING, isRunning);
		super.onSaveInstanceState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		Log.i(LogConstant.LOG_TAG, "onRestoreInstanceState()");
		setMsElapsed(savedInstanceState.getLong(SavedStateConstant.STATE_CHRONO_MS_ELAPSED));
		isRunning = !savedInstanceState.getBoolean(SavedStateConstant.STATE_CHRONO_IS_RUNNING);
		Log.e(LogConstant.LOG_TAG, " > IS RUNNNING : " + isRunning);
		mFirstCallTimer = false;
		startTimer();
		super.onRestoreInstanceState(savedInstanceState);
	}

	/** Update preference variables based on saved preferences */
	private void updateFromPreferences() {
		Log.i(LogConstant.LOG_TAG, "Update timer model from Preferences.");
		SharedPreferences prefs = getSharedPreferences(PokerTimerPreferences.GAME_PREFERENCES, Activity.MODE_PRIVATE);
		dataTimer = new MainDataTimer(getString(R.string.default_players)//
				, getString(R.string.default_stack)//
				, getString(R.string.default_timeround)//
				, getString(R.string.default_firstsmallblind)//
				, getString(R.string.default_blindstep)//
				, getString(R.string.default_nbprices));
		dataTimer.updateFromPreferences(prefs.getAll());
		Log.d(LogConstant.LOG_TAG, "Date timer pref :\n" + dataTimer.toString());

		updateTextViews();
		resetTimer();
	}

	/** Update text views (nb round, big blinds ...) */
	private void updateTextViews() {
		mCurrentRoundText.setText(getString(R.string.textview_roundnumber, dataTimer.getCurrentRound()));
		mSmallBlindText.setText(String.format("%.0f", dataTimer.getCurrentSmallBlind()));
		mBigBlindText.setText(String.format("%.0f", dataTimer.getCurrentBigBlind()));

		mCurrentRoundInfoText.setText(getString(R.string.textview_curroundinfo, dataTimer.getNbPlayers(), dataTimer.getCurrentRoundTime()));
		if (dataTimer.getBlinds().getBlindByRound(dataTimer.getCurrentRound() + 1) != null)
			mNextRoundInfoText.setText(getString(R.string.textview_nextroundinfo, dataTimer.getBlinds().getBlindByRound(dataTimer.getCurrentRound() + 1).getTime(), dataTimer.getBlinds().getBlindByRound(dataTimer.getCurrentRound() + 1).getSmallBlind(), dataTimer.getBlinds().getBlindByRound(dataTimer.getCurrentRound() + 1).getBigBlind()));
		// show/hide price list button
		if (dataTimer.isHasPrice()) {
			mPriceListButton.setVisibility(View.VISIBLE);
		} else {
			mPriceListButton.setVisibility(View.INVISIBLE);
		}
	}

	/** Display the next round dialog box */
	private void toastNextRoundDialog() {
		Toast.makeText(getApplicationContext() //
				, getString(R.string.toast_nextround, dataTimer.getCurrentRound(), dataTimer.getCurrentSmallBlind(), dataTimer.getCurrentBigBlind()) //
				, Toast.LENGTH_SHORT).show();
	}

	/** Start/Pause button listener */
	View.OnClickListener mStartListener = new OnClickListener() {
		public void onClick(View v) {
			if (mFirstCallTimer) {
				resetTimer();
			}
			if (mFirstCallTimer || !isRunning) {
				startTimer();
			} else if (isRunning) {
				stopTimer();
			}
			mFirstCallTimer = false;
		}
	};

	/** Start the chonometer and update UI */
	private void startTimer() {
		if (!isRunning) {
			mCountdown.start();
			mWakeLock.acquire(msElapsed);
			mStartPauseButton.setImageResource(android.R.drawable.ic_media_pause);
			isRunning = true;
		}
	}

	/** Stop the chonometer and update UI */
	private void stopTimer() {
		if (isRunning) {
			mCountdown.cancel();
			mCountdown = new CountDown(msElapsed, 1000);
			mStartPauseButton.setImageResource(android.R.drawable.ic_media_play);
			isRunning = false;
		}
	}
	
	/** Reset the countdown */
	private void resetTimer() {
		if (isRunning)
			stopTimer();
		mCountdown.cancel();
		mCountdown = new CountDown(dataTimer.getCurrentRoundTime() * 60000, 1000);
	}

	/** Reset button listener */
	View.OnClickListener mResetListener = new OnClickListener() {
		public void onClick(View v) {
			Toast.makeText(getApplicationContext(), R.string.toast_reset, Toast.LENGTH_SHORT).show();
			if (dataTimer.isDataFromUserPref()) {
				updateFromPreferences();
			} else {
				dataTimer = new MainDataTimer(getString(R.string.default_players)//
						, getString(R.string.default_stack)//
						, getString(R.string.default_timeround)//
						, getString(R.string.default_firstsmallblind)//
						, getString(R.string.default_blindstep)//
						, getString(R.string.default_nbprices));
				updateTextViews();
			}
			resetTimer();
		}
	};

	/** Next Round button listener */
	View.OnClickListener mNextRoundListener = new OnClickListener() {
		public void onClick(View v) {
			Log.d(LogConstant.LOG_TAG, "Next round click.");
			if (dataTimer.getCurrentRound() < dataTimer.getNbRounds()) {
				dataTimer.nextRound();
				updateTextViews();
			}
			resetTimer();
			toastNextRoundDialog();
		}
	};

	/** Previous Round button listener */
	View.OnClickListener mPreviousListener = new OnClickListener() {
		public void onClick(View v) {
			Log.d(LogConstant.LOG_TAG, "Previous click.");
			if (dataTimer.getCurrentRound() > 1) {
				dataTimer.previousRound();
				updateTextViews();
			}
			resetTimer();
			toastNextRoundDialog();
		}
	};

	/** Blind list button listener */
	View.OnClickListener mBlindListListener = new OnClickListener() {
		public void onClick(View v) {
			Log.d(LogConstant.LOG_TAG, "Blind list button click.");
			if (dataTimer.getBlinds() != null && dataTimer.getBlinds().getBlinds() != null) {
				Toast.makeText(getApplicationContext(), dataTimer.getBlinds().toString(), Toast.LENGTH_LONG).show();
			}
		}
	};

	/** Price list button listener */
	View.OnClickListener mPriceListListener = new OnClickListener() {
		public void onClick(View v) {
			Log.d(LogConstant.LOG_TAG, "Price list button click.");
			Toast.makeText(getApplicationContext() //
					, String.format("%s", dataTimer.getPricePercentageToString()) //
					, Toast.LENGTH_LONG).show();
		}
	};

	/**
	 * Set the elapsed time to the timer
	 * 
	 * @param ms
	 */
	public void setMsElapsed(long ms) {
		msElapsed = ms;
		mCountdown = new CountDown(msElapsed, 1000);
	}

	/** Countdown Inner class */
	public class CountDown extends CountDownTimer {

		/** Default constructor based on coundown */
		public CountDown(long millisInFuture, long countDownInterval) {
			super(millisInFuture, countDownInterval);
			msElapsed = millisInFuture;
			mCountdownTextView.setText(TimerFormatter.formatMsToFormattedTime(millisInFuture));
		}

		@Override
		public void onFinish() {
			msElapsed = 0;
			resetTimer();
			dataTimer.nextRound();
			updateTextViews();
			startTimer();
			toastNextRoundDialog();
			// Launch sound
			if (mIsActiveSound)
				RingtoneManager.getRingtone(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)).play();
			// Vibrate
			if (mIsActiveVibrate) {
				Vibrator v = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
				v.vibrate(1000);
			}
		}

		@Override
		public void onTick(long millisUntilFinished) {
			msElapsed = millisUntilFinished;
			mCountdownTextView.setText(TimerFormatter.formatMsToFormattedTime(millisUntilFinished));
		}
	}

}
